package server;


import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
import java.util.HashMap;

import commons.Message;
import commons.OMGProtocol;
import commons.World;

/**
 * 
 * A single thread for each connection to a client
 * this class gets messages, sends messages, by
 * envoking the DFA
 *
 */
class OMGPConnectionThread extends Thread {
	
	
	private Socket serverSock;
	private int clientID;
	private HashMap<Integer, World> games;

	OMGPConnectionThread(Socket serverSock, int clientID, HashMap<Integer, World> games) {
		this.games = games;
		this.serverSock = serverSock;
		this.clientID = clientID;
	}

	 public void run() {

			try {
								
				DataOutputStream out = new DataOutputStream(new BufferedOutputStream(this.serverSock.getOutputStream()));
			    DataInputStream in = new DataInputStream(new BufferedInputStream(
						    this.serverSock.getInputStream()));

			    
			    OMGProtocolForServer oProtocol = 
			    	new OMGProtocolForServer(OMGPServer.SERVER_NAME, games, clientID);
			    
			    // Send authentication request
				Message messageToSend = null;
				Message currentClientMessage = new Message();
				int pastState = -1;
				do {		
					if(oProtocol.getState() != pastState) {
						System.err.println("["+ clientID + "] Server is in state: " + oProtocol.getStateDescription());
						pastState = oProtocol.getState();
					}
					
					// Get the latest message
					if(in.available()>0 && currentClientMessage.isRead()) {
						currentClientMessage = new Message(in);
						System.err.println("[" + clientID + "] Message received: " + currentClientMessage.getMessageDescription());
					}
					
					// Run the DFA
					messageToSend = oProtocol.runDFA(currentClientMessage);
					
					// Check if there's a message to send
					if(messageToSend != null) {
						messageToSend.send(out);
					}
					
				}while (oProtocol.getState() != OMGProtocol.NONE);
				System.err.println("[Thread closed]");
				
			    
			    out.close();
			    in.close();
			    this.serverSock.close();

			} 
			catch (SocketException e) {
				System.err.println(" Socket Exception ->"+e.getMessage());
			}
			catch (IOException e) {
				System.err.println(" IOException ->"+e.getMessage());
				e.printStackTrace();
			}
			catch (ClassNotFoundException e) {
				System.err.println(" ClassNotFoundException ->"+e.getMessage());
			}
			
		}
	 
	 public void close()
	 {
		 try {
			this.serverSock.close();
		} catch (IOException e) {
			
			e.printStackTrace();
		}
	 }
	
	
}